	; This is just a trick to create constants
	.ORIG 2048
ASize:	; Size of the array is 512 elements (2048 bytes) 
	.ORIG 1000
ItNum:	;  Number of sorting iterations	
	.ORIG 8192
Stack:	; Stack begins at the very top of memory

	.orig	0x200
SysStackTop:
	.orig	0x200
	
	; Save registers to system stack
	addi    rd,rd,-32
	sw		t0,0(rd)
	sw		t1,4(rd)
	sw		t2,8(rd)
	sw		t3,12(rd)
	sw		a0,16(rd)
	sw		a1,20(rd)
	sw		a2,24(rd)
	sw		a3,28(rd)
	xor 	t0,t0,t0
Timer:
	rctl	a1,ctl1
	;Check to see if it's a timer interrupt
	eqi		t1,a1,1
	beqz	t1,Key			;dev isn't timer, try key
	
	;It's a timer interrupt
	;is the sw0 on?
	lw		t1,0xF004(t0)	;t1 = switches
	andi	t1,t1,1			;t1 = mask switch 0
	beqz	t1,CLKTClearFlash	;if sw0 is off, clear this
	;if sw0 is on, inc HalfSec
	lw		t2,HalfSec(t0)	;t2 = HalfSec
	addi	t2,t2,1			;HalfSec++
	sw		t2,HalfSec(t0)	;store HalfSec
	eqi		t3,t2,50		;if(HalfSec == 50)
	beqz	t3,CLKTCont1
	;flash seccount
	sw		t0,HalfSec(t0)	;HalfSec = 0
	lw		t2,LEDVal(t0)	;t2 = LEDVal
	xori	t2,t2,0xC0		;flip C0
	sw		t2,LEDVal(t0)	;store LEDVal
	beq		t0,t0,CLKTCont1
	
CLKTClearFlash:
	sw		t0,HalfSec(t0)	;HalfSec = 0
	sw		t0,LEDVal(t0)	;LEDVal = 0
CLKTCont1:
	;inc timercount
	lw		t2,TimerCount(t0);t2 = TimerCount
	addi	t2,t2,1			 ;TimerCount++
	sw		t2,TimerCount(t0);store TimerCount
	eqi		t3,t2,100		 ;if(TimerCount == 100) t3 = 1;
	beqz	t3,DispChooser
	
	;if TimerCount = 100
	;store 0 in timercount
	sw		t0,TimerCount(t0); TimerCount = 0
	;inc seccount
	lw		t2,SecCount(t0)	;t2 = SecCount
	addi	t2,t2,1			;SecCount++
	sw		t2,SecCount(t0)	;Store SecCount
	eqi		t3,t2,60		;if(SecCount == 60) t3 = 0;
	beqz	t3,SortTimer

	;if SecCount = 60
	sw		t0,SecCount(t0)	;SecCount = 0
	;inc minLo
	lw		t2,MinLo(t0)	;t2 = MinLo
	addi	t2,t2,1			;MinLo++
	sw		t2,MinLo(t0)	;Store MinLo
	eqi	t3,t2,10			;if(MinLo == 10) t3 = 0;
	beqz	t3,SortTimer

	;if MinLo = 10
	sw		t0,MinLo(t0)	;MinLo = 0
	;inc MinHi
	lw		t2,MinHi(t0)	;t2 = MinHi
	addi	t2,t2,16		;MinHi++
	sw		t2,MinHi(t0)	;Store MinHi
	eqi	t3,t2,96			;if(MinHi == 6*16) t3 = 0
	beqz	t3,SortTimer
	
	;if MinHi = 6
	sw		t0,MinHi(t0)	;MinHi = 0
	;inc HourCount
	lw		t2,HourCount(t0);t2 = HourCount
	addi	t2,t2,1			;HourCount++
	sw		t2,HourCount(t0);Store HourCount
	eqi		t3,t2,24		;if(HourCount == 24) t3 = 0
	beqz	t3,CLKNormHour
	
	;hours = 24, reset all hour counters and branch to SortTimer
	sw		t0,HourCount(t0);HourCount = 0
	sw		t0,HourLo(t0)	;HourLo = 0
	sw		t0,HourHi(t0)	;HourHi = 0
	beq		t0,t0,SortTimer
	
CLKNormHour:
	;inc HourLo
	lw		t2,HourLo(t0)	;t2 = HourLo
	addi	t2,t2,256		;HourLo++
	sw		t2,HourLo(t0)	;Store HourLo
	eqi		t3,t2,2560		;if(HourLo == 10*256) t3 = 0
	beqz	t3,SortTimer
	
	;if HourLo = 10
	sw		t0,HourLo(t0)		;HourLo = 0
	;inc HourHi
	lw		t2,HourHi(t0)	;t2 = HourHi
	addi	t2,t2,4096		;HourHi++
	sw		t2,HourHi(t0)		;Store HourLo

SortTimer:
	lw	a1,Hex1(t0)
	addi	a1,a1,1
	sw	a1,Hex1(t0)
	eqi t3,a1,10 
	beqz t3,DispChooser

	;if Hex1 = 10
  	sw  t0,Hex1(t0) ;Hex1 = 0
  	;inc Hex1
 	lw  a1,Hex2(t0) ;a1 = Hex2
 	addi a1,a1,16  	;Hex2++
  	sw  a1,Hex2(t0) ;Store Hex2
  	eqi t3,a1,160    
  	beqz t3,DispChooser
  	;if hex2=10
  	sw  t0,Hex2(t0) ;Hex2 = 0
  	;inc Hex1
 	lw  a1,Hex3(t0) ;a1 = Hex3
 	addi a1,a1,256  ;Hex3++
  	sw  a1,Hex3(t0) ;Store Hex3
  	eqi t3,a1,2560 
  	beqz t3,DispChooser
  	;if hex3=10
  	sw  t0,Hex3(t0) ;Hex3 = 0
  	;inc Hex1
 	lw  a1,Hex4(t0) ;t2 = Hex4
 	addi a1,a1,4096  	;Hex4++
  	sw  a1,Hex4(t0) ;Store Hex4
  	;we limit the count to 4999 as our max
  	eqi t3,a1,20480;
  	beqz t3,DispChooser 
  	sw t0,Hex4(t0)
	;END SORT TIMER CODE
	beq		t0,t0,DispChooser
	
Key:
	eqi		t1,a1,2
	beqz	t1,Switch		;device isn't key, try switch

	lw		t1,0xF004(t0)	;t1 = switches
	andi	t1,t1,0x200		;t1 = mask switch 9
	beqz	t1,CLKKey		;if sw9 is off, goto CLK Key, else continue
	
	; We had a keys interrupt for the sort
	; Clear the IP bit in KCTL
	lw	a1,0xf000(t0)
	andi	a2,a1,0x10
	xor	a1,a1,a2
	sw	a1,0xf000(t0)
	;check the status of KEY[0]
	lw	t2,0xf000(t0)
	andi	t2,t2,0x1
	xori	t2,t2,1
	beqz t2,IntExit
	
	; Reset everything and return to the start of the sort program since key[0] is 1
	;Restore the Array to the original value
	lw 		t1,ArrayRestore(t0)
	sw 		t1,Array(t0)
	wctl	ctl0,s0
	wctl	ctl1,s0
	beq		t0,t0,Main
	;addi rc,s0,SortMain ;addi rc,s0,SortMain
	;reti
	

	
IntExit:
	; Restore register values and return from interrupt
	lw		t0,0(rd)
	lw		t1,4(rd)
	lw		t2,8(rd)
	lw		t3,12(rd)
	lw		a0,16(rd)
	lw		a1,20(rd)
	lw		a2,24(rd)
	lw		a3,28(rd)
	addi	rd,rd,32
	reti
	
	.orig   0x400
Main:
	;xor	t0,t0,t0 ;0 variable
	xor		s0,s0,s0 ;0 variable
	; Set system stack pointer
	addi	rd,s0,SysStackTop
	
	;Enable Timer Interrupts @ every 10ms
	;tcnt = 10
	addi	t1,s0,10 ;addi	t1,s0,10
	sw		t1,0xF104(s0) 	
	;tctl = 5 (0101), AR=1, IE=1
	addi	t1,s0,5			
	sw		t1,0xF100(s0)	
	
	;Enable Switch Interrupts
	addi	t1,s0,0x800
	sw		t1,0xF004(s0)
	
	;Enable Key Interrupts
	ori		t1,s0,0x20
	sw		t1,0xF000(s0)
	
	;Enable Global Interrupts
	addi	t1,s0,5
	wctl 	ctl0,t1

SortMain:
	sw		s0,TimerStatus(s0)
	sw  	s0,TestD(s0)
	sw  	s0,Hex1(s0)
	sw  	s0,Hex2(s0)
	sw  	s0,Hex3(s0)
	sw  	s0,Hex4(s0)
	
InfLoop:
	beq		s0,s0,InfLoop
;	XOR	S0,S0,S0	; Not using GP, we use S0 to hold value zero
;	ADDI	SP,S0,Stack	; Put SP at top of our memory
;	;or	re,s0,s0 ;holding interupt nesting level
;	; Initialize the array
;	ADDI	T0,S0,Array	; T0 = Address of array
;	ADDI	T1,S0,ASize
;	ADD		T1,T0,T1	; T1 = End of array
;	ADDI	T2,S0,1000	; T2 is 1000 
;	SUBI	T0,T0,-4	; Array[0] already initialized
;Init:
;	SW		T2,0(T0)
;	ADDI	T2,T2,7
;	ADDI	T0,T0,4
;	SUB		T3,T0,T1
;	LTI		T3,T3,0
;	BNEZ	T3,Init
;	
;	ADDI	T0,S0,ItNum	; Iteration count kept in T0
;	;init on interupts, using t1 to write stuff
;
;Loop:
;	SUBI	SP,SP,4
;	SW		T0,0(SP)	; Save loop counter to stack
;	ADDI	A0,S0,Array	; A0 - Address of array
;	ADDI	A1,A0,ASize	; A1 - End of array
;	ADDI	A2,S0,0		; Sort in ascending order
;	JRL		RA,Sort(S0)	; Call Sort
;	BEQZ	RV,Error
;	ADDI	A0,S0,Array	; A0 - Address of array
;	ADDI	A1,A0,ASize	; A1 - End of array
;	ADDI	A2,S0,1		; Sort in descending order
;	ADDI	T0,S0,Sort
;	JRL		RA,0(T0)	; Call Sort
;	BEQZ	RV,Error
;	LW		T0,0(SP)	; Restore loop counter from stack 
;	ADDI	SP,SP,4
;	SUBI	T0,T0,1
;	SW		T0,0xF804(S0)	; Send counter to LEDR display
;	BNEZ	T0,Loop
;
;	ADDI	T0,S0,Array	; T0 = Address of array
;	ADDI	T1,T0,ASize	; T1 = End of array
;	ADDI	T2,S0,1000	; T2 is 1000
;	LW	A0,0(T0)
;	ADDI	A1,S0,Stack
;	BNE	A0,A1,Error
;	ADDI	T0,T0,4
;Check:
;	BEQ	T1,T0,Done
;	SUBI	T1,T1,4
;	LW	A0,0(T1)
;	BNE	A0,T2,Error
;	ADDI	T2,T2,7
;	BEQ	T2,T2,Check
;Done:
;	xori	t1,s0,1
;	sw		t1,TimerStatus(s0) ;1- no longer counting
;	;xor	t1,t1,t1
;	;sw		t1,0xF100(s0) ;disable timer device
;	;sw		t1,0xF104(s0)
;	ADDI	T0,S0,0xFFFF	; Display FFFF
;	SW	T0,0xF804(S0)
;	BNEZ	T0,Done		; Loops forever
;
;Error:
;	;BEQ		t0,t0,Error		;Loops Forever
;	ADDI	T0,S0,0xEEEE	; Display EEEE
;	SW	T0,0xF800(S0)
;	BNEZ	T0,Error	; Loops forever
;	
;Sort:	; Sort(beg,end,order)
;	; Sorts an array that starts at beg and ends at end
;	; If order==0, sorts in ascending order (low to high)
;	; If order==1, sorts in descending order (high to low)
;	ADDI	T0,A0,0
;LoopI:
;	BEQ	T0,A1,EndI
;	ADDI	T1,T0,4
;LoopJ:	
;	BEQ	T1,A1,EndJ
;	LW	T2,0(T0)
;	LW	T3,0(T1)
;	BNEZ	A2,Descend
;	LT	RV,T2,T3
;	BEQ	RV,RV,Decide
;Descend:
;	LT	RV,T3,T2
;Decide:
;	BNEZ	RV,NoSwap
;Swap:
;	SW	T2,0(T1)
;	SW	T3,0(T0)
;NoSwap:		
;	ADDI	T1,T1,4
;	BEQ	T1,T1,LoopJ
;EndJ:	
;	ADDI	T0,T0,4
;	BEQ	T0,T0,LoopI
;EndI:
;	ADDI	RV,RV,1
;	JRL	T0,0(RA)

ArrayRestore:
	.WORD Stack	
Array:
	.WORD Stack
	
TimerCount:
	nop
SecCount:
	nop
MinLo:
	nop
MinHi:
	nop
HourLo:
	nop
HourHi:
	nop
HourCount:
	nop
HalfSec:
	nop
LEDVal:
	nop
TestD:
	.word 0x00000000
TimerStatus:
	.word 0x00000000	
Hex4:
	.word 0x00000000
Hex3:
	.word 0x00000000
Hex2:
	.word 0x00000000
Hex1:
	.word 0x00000000
	
Switch:
	lw		t1,0xF004(t0)	;t1 = switches
	andi	t2,t1,0x200		;t2 = mask switch 9
	bnez	t2,IntExit		;if sw9 is on, just exit
	andi	t2,t1,1			;t2 = mask switch 1
	beqz	t2,CLKSoff		;if sw0 is off, goto Soff, else stay on
CLKSon:
	;cheat HalfSec to 50 next go around
	addi	t2,t0,49		;HalfSec++
	sw		t2,HalfSec(t0)	;store HalfSec
	;addi	t1,t0,32
	;sw		t1,0xF000(t0) ;turn on key interrupts
	beq		t0,t0,CLKSEnd
CLKSoff:
	sw		t0,HalfSec(t0)	;HalfSec = 0
	sw		t0,LEDVal(t0)	;LEDVal = 0
	;sw		t0,0xF000(t0)	;turn off key interrupts
CLKSEnd:
	;Reset Switch Interrupts
	addi	t1,t0,0x800
	sw		t1,0xF004(t0)

	beq	t0,t0,IntExit
	
CLKKey:	
	lw		t1,0xF004(t0)	;t1 = switches
	andi	t1,t1,1			;t1 = mask switch 0
	beqz	t1,IntExit		;if sw0 is off, forget interrupt
	
	lw		t1,0xF000(t0)	;t1 = keys
	andi	t2,t1,1			;t2 = mask key 0
	beqz	t2,K0on			;Key0 is on
	andi	t2,t1,2			;t2 = mask key 1
	beqz	t2,K1on			;Key1 is on
	andi	t2,t1,4			;t2 = mask key 2
	beqz	t2,K2on			;Key2 is on
	andi	t2,t1,8			;t2 = mask key 3
	beqz	t2,K3on			;Key3 is on
	beq		t0,t0,KEnd		;no key? foggedabouddit
	
K0on:
	sw 		t0,SecCount(t0)	;resets seconds
	lw		t1,MinLo(t0)	;t1 = MinLo
	lw		t2,MinHi(t0)	;t2 = MinHi
	
	beqz	t1,KDownHi 		;if(MinLo = 0)
	subi	t1,t1,1			;MinLo --;
	sw		t1,MinLo(t0)	;store MinLo
	beq		t0,t0,KEnd
KDownHi:
	beqz	t2,KDoubleDown	;if(MinHi = 0 && MinLo = 0)
	subi	t2,t2,16		;MinHi -1*16;
	sw		t2,MinHi(t0)	;store MinHi
	addi	t1,t0,9			;t1 = 9
	sw		t1,MinLo(t0)	;MinLo = 9
	beq		t0,t0,KEnd
KDoubleDown:
	addi	t1,t0,80		;t1 = 5*16
	sw		t1,MinHi(t0)	;MinHi = 5*16
	addi	t1,t0,9			;t1 = 9
	sw		t1,MinLo(t0)	;MinLo = 9
	beq		t0,t0,K2on		;dec hour
	
K1on:
	sw 		t0,SecCount(t0)	;resets seconds
	lw		t1,MinLo(t0)	;t1 = MinLo
	lw		t2,MinHi(t0)	;t2 = MinHi

	addi	t1,t1,1
	sw		t1,MinLo(t0)
	addi	t3,t0,10
	beq		t1,t3,KUpHi		;MinLo Wraps @10
	beq		t0,t0,KEnd
KUpHi:
	addi	t2,t2,16
	sw		t0,MinLo(t0)
	sw		t2,MinHi(t0)
	addi	t3,t0,96		;t3 = 6*16
	beq		t2,t3,KDoubleUp	;if(MinLo = 9 && MinHi = 5*16)
	beq		t0,t0,KEnd
KDoubleUp:
	sw		t0,MinHi(t0)	;MinHi = 0
	beq 	t0,t0,K3on		;inc hour

K2on:
	lw		t1,HourCount(t0)
	beqz	t1,KDoubleDownHour
	subi	t1,t1,1
	sw		t1,HourCount(t0)
	lw		t1,HourLo(t0)
	beqz	t1,KDownHourHi
	subi	t1,t1,256
	sw		t1,HourLo(t0)
	beq		t0,t0,KEnd
KDownHourHi:
	lw		t1,HourHi(t0)
	subi	t1,t1,4096		;sub 1*4096
	sw		t1,HourHi(t0)
	addi	t1,t0,2304
	sw		t1,HourLo(t0)
	beq		t0,t0,KEnd
KDoubleDownHour:
	addi	t1,t0,768		;t1 = 3*256
	sw		t1,HourLo(t0)	;HourLo = 3*256
	addi	t1,t0,8192		;t2 = 2*4096
	sw		t1,HourHi(t0)	;HourHi = 2*4096
	addi	t1,t0,23		;t3 = 23
	sw		t1,HourCount(t0);HourCount = 23
	beq		t0,t0,KEnd

K3on:						;inc the hours
	lw		t1,HourCount(t0)
	addi	t1,t1,1
	sw		t1,HourCount(t0)
	addi	t2,t0,24
	beq		t1,t2,KDoubleUpHour ;HourCount == 24
	lw		t1,HourLo(t0)
	addi	t1,t1,256			;HourLo += 1*256
	sw		t1,HourLo(t0)
	addi	t2,t0,2560
	beq		t1,t2,KUpHourHi		;HourLo = 10
	beq		t0,t0,KEnd
KDoubleUpHour:
	sw		t0,HourCount(t0);HourCount = 0
	sw		t0,HourLo(t0)	;HourLo = 0
	sw		t0,HourHi(t0)	;HourHi = 0
	beq		t0,t0,KEnd
KUpHourHi:
	sw		t0,HourLo(t0)	;HourLo = 0
	lw		t1,HourHi(t0)
	addi	t1,t1,4096		;HourHi += 1*4096
	sw		t1,HourHi(t0)
	beq		t0,t0,KEnd
	
KEnd:
	;Reset Key Interrupts
	addi	t1,t0,32
	sw		t1,0xF000(t0)
	
	beq		t0,t0,IntExit
	
	

	
DispChooser: ;choose displayer based on sw9 state
	lw		t1,0xF004(t0)	;t1 = switches
	andi	t1,t1,0x200		;t1 = mask switch 9
	bnez	t1,SortDispTimer;if sw9 is on, goto SortDispTimer, else continue
	
	;always display clock's seccount
	lw		t2,SecCount(t0)	;t2 = SecCount
	lw		t3,LEDVal(t0)	;t3 = LEDVal
	or		t2,t2,t3		;Combine SecCount and LEDVal
	sw		t2,0xf808(t0)	;LEDG = Combined
	
	
CLKDispTimer:

	;display MinLo,MinHi,HourLo,HourHi
	lw		t2,MinLo(t0)	;t2 = MinLo
	add		t3,t2,t0		;t3 = ToDisplay
	lw		t2,MinHi(t0)	;t2 = MinHi
	add		t3,t3,t2		;t3 = ToDisplay
	lw		t2,HourLo(t0)	;t2 = HourLo
	add		t3,t3,t2		;t3 = ToDisplay
	lw		t2,HourHi(t1)	;t2 = HourHi
	add		t3,t3,t2		;t3 = ToDisplay
	;display hourcount
	sw		t3,0xf800(t0)
	
	; Clear the IP bit in TCTL
	lw 		a1,0xf100(t0)
	andi 	a2,a1,0x2
	xor 	a1,a1,a2
	sw 		a1,0xf100(t0)
	
	beq		t0,t0,IntExit

SortDispTimer:
	lw		t2,SecCount(t0)	;t2 = SecCount
	sw		t2,0xf808(t0)	;LEDG = Combined


  ;display Hex1, Hex2, Hex3, Hex4
	lw  	t2,Hex1(t0) ;t2 = Hex1
	add  	t3,t2,t0  ;t3 = ToDisplay
	lw  	t2,Hex2(t0) ;t2 = Hex2
	add  	t3,t3,t2  ;t3 = ToDisplay
	lw  	t2,Hex3(t0) ;t2 = Hex3
	add  	t3,t3,t2  ;t3 = ToDisplay
	lw  	t2,Hex4(t0) ;t2 = Hex3
	add  	t3,t3,t2  ;t3 = ToDisplay
	sw 		t3,0xf800(t0)
	
	; Clear the IP bit in TCTL
	lw 		a1,0xf100(t0)
	andi 	a2,a1,0x2
	xor 	a1,a1,a2
	sw 		a1,0xf100(t0)
	
	beq		t0,t0,IntExit